package paodekuai

import (
	"errors"
	"fmt"
	"gitee.com/yuya000/cards-game-server-go/logwarp"
	"gitee.com/yuya000/cards-game-server-go/server"
	"github.com/BurntSushi/toml"
	"strconv"
	"strings"
)

const (
	GameName = "paodekuai"
)

type GameConfig struct {
	Name string `xorm:"name"`
	Help string `xorm:"help"`
	Conf string `xorm:"conf"`
	Opt  string `xorm:"opt"`
}

type PaosDeKuaiOpt struct {
	GameType               string   `toml:"type"` // 游戏类型
	FangZhuPayCostAndRound []string `toml:"fangzhu_pay_cost_and_round"`
	PingTanPayCostAndRound []string `toml:"pingtan_pay_cost_and_round"`
	MethodOfPayment        []string `toml:"method_of_payment"`
	Number                 []int    `toml:"number"`
	Rules                  []string `toml:"rules"`
}

type PaoDeKuaiConf struct {
	maxRound      int
	cost          int
	payment       int
	maxPlayers    int
	showHoldPaisN bool
	mustPut       bool
}

func NewPaoDeKuaiConf(args server.Args) (*PaoDeKuaiConf, error) {
	var (
		gc   GameConfig
		conf PaoDeKuaiConf
		opt  PaosDeKuaiOpt
	)
	exist, err := server.DBEngine.Where("name=?", GameName).Get(&gc)
	if err != nil {
		return nil, err
	}
	if !exist {
		return nil, errors.New("游戏配置不存在")
	}
	if err := toml.Unmarshal([]byte(gc.Opt), &opt); err != nil {
		return nil, err
	}
	if len(args["method_of_payment"]) != 1 {
		logwarp.Std().Warningln("参数错误 method_of_payment", args["method_of_payment"])
		return nil, fmt.Errorf("参数错误 method_of_payment %v", args["method_of_payment"])
	}
	methodOfPayment := args["method_of_payment"][0]
	switch methodOfPayment {
	case 0:
		conf.payment = 0
	case 1:
		conf.payment = 1
	default:
		logwarp.Std().Warningln("参数错误 method_of_payment", args["method_of_payment"])
		return nil, fmt.Errorf("参数错误 method_of_payment %v", args["method_of_payment"])
	}
	if len(args["cost_and_round"]) != 1 {
		logwarp.Std().Warningln("参数错误 cost_and_round", args["cost_and_round"])
		return nil, fmt.Errorf("参数错误 cost_and_round %v", args["cost_and_round"])
	}
	costAndRoundIndex := args["cost_and_round"][0]
	var selectedCostAndRound string
	switch methodOfPayment {
	case 0:
		if costAndRoundIndex >= len(opt.FangZhuPayCostAndRound) {
			logwarp.Std().Warningln("参数错误 cost_and_round", args["cost_and_round"])
			return nil, fmt.Errorf("参数错误 cost_and_round %v", args["cost_and_round"])
		}
		selectedCostAndRound = opt.FangZhuPayCostAndRound[costAndRoundIndex]
	case 1:
		if costAndRoundIndex >= len(opt.PingTanPayCostAndRound) {
			logwarp.Std().Warningln("参数错误 cost_and_round", args["cost_and_round"])
			return nil, fmt.Errorf("参数错误 cost_and_round %v", args["cost_and_round"])
		}
		selectedCostAndRound = opt.PingTanPayCostAndRound[costAndRoundIndex]
	}
	cost_round := strings.Split(selectedCostAndRound, "-")
	if len(cost_round) != 2 {
		logwarp.Std().Warningln("参数错误 cost_and_round", cost_round)
		return nil, fmt.Errorf("参数错误 cost_and_round %v", cost_round)
	}
	if conf.maxRound, err = strconv.Atoi(cost_round[0]); err != nil {
		logwarp.Std().Warningln("参数错误 cost_and_round", cost_round[0])
		return nil, fmt.Errorf("参数错误 cost_and_round %v", cost_round[0])
	}
	if conf.cost, err = strconv.Atoi(cost_round[1]); err != nil {
		logwarp.Std().Warningln("参数错误 cost_and_round", cost_round[1])
		return nil, fmt.Errorf("参数错误 cost_and_round %v", cost_round[1])
	}
	if len(args["player_n"]) != 1 {
		logwarp.Std().Warningln("参数错误 player_n", args["player_n"])
		return nil, fmt.Errorf("参数错误 player_n %v", args["player_n"])
	}
	playernIndex := args["player_n"][0]
	if playernIndex >= len(opt.Number) {
		logwarp.Std().Warningln("参数错误 player_n", args["player_n"])
		return nil, fmt.Errorf("参数错误 player_n %v", args["player_n"])
	}
	conf.maxPlayers = opt.Number[playernIndex]
	if len(args["rules"]) > 0 {
		rules := args["rules"]
		for _, rule := range rules {
			switch rule {
			case 0:
				conf.showHoldPaisN = true
			case 1:
				conf.mustPut = true
			}
		}
	}
	return &conf, nil
}

type PaoDeKuaiFactory struct{}

func (f *PaoDeKuaiFactory) NewGame(player *server.Player, args server.Args) (server.Game, server.Exception) {
	id, err := server.GenerateGameID()
	if err != nil {
		logwarp.Std().Warningln(err)
		return nil, server.SystemException
	}
	conf, err := NewPaoDeKuaiConf(args)
	if err != nil {
		logwarp.Std().Warningln(err)
		return nil, server.ArgsException
	}
	if player.CurrentClub.HouseCards < conf.cost {
		return nil, server.CostDeficiencyException
	}
	if err := server.SendOK(player.Session, &server.NewGameResp{
		Seq:     0,
		HouseNo: id,
	}, server.MessageTypeCreateGame); err != nil {
		logwarp.Std().Warningln(err)
	}
	paodekuai := &Paodekuai{
		stat:         StatWait,
		id:           id,
		name:         GameName,
		conf:         conf,
		players:      server.NewPlayerMap(),
		args:         args,
		readyPlayers: server.NewPlayerMap(),
		sequence:     make([]*server.Player, conf.maxPlayers),
		owner:        player,
		holdPais:     make(map[string]map[string]bool),
		currentRing:  1,
		bombs:        make(map[string]int),
		bombsEntry:   make(map[string]int),
		ballotBox:    make(map[string]string),
	}
	paodekuai.players.Store(player.Id, player)
	paodekuai.sequence[0] = player
	return paodekuai, nil
}

func (f *PaoDeKuaiFactory) Free(game server.Game) {}
